package com.qinge.blog.security.filter;

import com.alibaba.fastjson.JSON;
import com.qinge.blog.constant.Constant;
import com.qinge.blog.entity.BlogUser;
import com.qinge.blog.utils.jwt.JwtUtil;
import com.qinge.blog.utils.redis.RedisUtil;
import com.qinge.blog.utils.result.ResultCode;
import com.qinge.blog.utils.result.ResultTool;
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @author QDW
 * @date 2022/5/6 8:42
 * @description JWT
 **/
@Component
public class JavaWebTokenAuthenticationTokenFilter extends GenericFilterBean {

    @Resource
    private RedisUtil redisUtil;

    // 登录的时候可以没有token
    private String defaultFilterProcessUrl = "/blog/api/user/login";
    private String registerUrl="/blog/api/user/register";

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request= (HttpServletRequest) servletRequest;
        HttpServletResponse response= (HttpServletResponse) servletResponse;

        // 获取token
        String token = request.getHeader("token");

        // 登录直接放行
        if (defaultFilterProcessUrl.equals(request.getServletPath()) || registerUrl.equals(request.getServletPath())
                || request.getServletPath().contains(Constant.FILE_PREFIX.getValue()) || request.getServletPath().contains(Constant.UPLOAD_API.getValue()) ) {
            // 放行
            filterChain.doFilter(request, response);
            return;
        }

        // 解析token
        String userid;

        if(Objects.isNull(token)|| "null".equals(token) || !JwtUtil.isSigned(token)){
            // 如果验证码验证失败，直接返回
            response.setContentType("text/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(ResultTool.fail(ResultCode.USER_TOKEN_INVALID)));
            return;
        }else if(JwtUtil.isExpired(token)){
            // 判断JWT是否过期
            response.setContentType("text/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(ResultTool.fail(ResultCode.USER_TOKEN_EXPIRED)));
            return;
        }else{
            Claims claims = JwtUtil.parseJWT(token);
            userid = claims.getSubject();
        }

        // 从redis中获取用户信息
        String redisKey = "login:" + userid;
        BlogUser loginUser = (BlogUser) redisUtil.getCacheObject(redisKey);
        if(Objects.isNull(loginUser)){
            response.setContentType("text/json;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(ResultTool.fail(ResultCode.USER_NOT_LOGIN)));
            return;
        }

        // 存入SecurityContextHolder
        // TODO 获取权限信息封装到Authentication中
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        // 放行
        filterChain.doFilter(request, response);
    }
}
